package com.zx.process.impl;

import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zx.converter.Converter;
import com.zx.exception.DataParseException;
import com.zx.model.DataClassModel;
import com.zx.model.DataFieldModel;
import com.zx.model.HandlerArgs;
import com.zx.process.AbstractDataConfigProcess;
import com.zx.process.ProcessHandler;
import com.zx.util.ClassUtil;
import com.zx.util.StringUtils;

/**
 * @Project: dataParse
 * @Title: TextDataConfigProcess
 * @Description: 文本格式数据解析类
 * @author: zhangxue
 * @date: 2017年11月18日下午3:19:15
 * @version v1.0
 */
public class TextDataConfigProcess<T> extends AbstractDataConfigProcess<T> {
	
	private static Logger logger = LoggerFactory.getLogger(TextDataConfigProcess.class);
	
	public TextDataConfigProcess(DataClassModel<T> dataConfig) {
		this.setDataConfig(dataConfig);
		logger.info("初始化文本格式数据解析器【{}】", dataConfig.toString());
	}

	@Override
	public String[] splitAndChecked(String line) throws DataParseException {
		if(line == null || line.length() == 0) {
			throw new DataParseException("数据不能为空");
		}
		
		String[] array = StringUtils.split(line, this.getDataConfig().getSplit());//将一行数据进行分割
		if(array == null || array.length == 0) {//校验数据是否为空
			throw new DataParseException("使用分隔符" + this.getDataConfig().getSplit() + "未获得结果,line=" + line);
		}
		// 校验这一行的数据
		ProcessHandler checkedHandler = this.getDataConfig().getCheckedHandler();
		boolean handler = checkedHandler.handler(new HandlerArgs(array.length));
		
		if(!handler) {//校验未通过
			throw new DataParseException("数据格式校验失败,line=" + line);
		}
		
		return array;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T parse(String[] strs) throws DataParseException {
		if(strs == null || strs.length == 0) {
			throw new DataParseException("数据不能为空");
		}
		return (T)toBean(strs);
	}

	@Override
	public T parse(String line) throws DataParseException {
		String[] strs = this.splitAndChecked(line);
		return this.parse(strs);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> parseList(String[] strs) throws DataParseException {
		if(strs == null || strs.length == 0) {
			throw new DataParseException("数据不能为空");
		}
		//开启解析为集合的功能
		if(super.getDataConfig().getArrayInterval() == 0) {
			throw new DataParseException("arrayInterval = 0 ，未开启集合解析功能，无法将单行数据解析为集合");
		} else {//解析为对象
			return (List<T>)toList(strs);
		}
	}
	
	@Override
	public List<T> parseList(String line) throws DataParseException {
		String[] strs = this.splitAndChecked(line);
		return this.parseList(strs);
	}

	@Override
	public List<T> parseList(List<String[]> lines) throws DataParseException {
		if(lines == null || lines.isEmpty()) {
			throw new DataParseException("数据不能为空");
		}
		//开启解析为集合的功能
		List<T> list = new ArrayList<T>(lines.size());
		for (String[] strs : lines) {
			list.add(this.parse(strs));
		}
		return list;
	}

	@Override
	public List<List<T>> parseListForArrayInterval(List<String[]> lines)
			throws DataParseException {
		if(lines == null || lines.isEmpty()) {
			throw new DataParseException("数据不能为空");
		}
		//开启解析为集合的功能
		List<List<T>> list = new ArrayList<List<T>>(lines.size());
		for (String[] strs : lines) {
			list.add(this.parseList(strs));
		}
		return list;
	}
	
	//##################################1. 内部核心处理方法  ####################################################//
	/**
	 * @title 将一行数据拆分后的数组解析为对象
	 * @param strs
	 * @return
	 * @throws DataParseException
	 * @author: xue.zhang
	 * @date 2019年1月15日下午2:21:26
	 */
	private Object toBean(String[] strs) throws DataParseException {
		if(strs == null || strs.length == 0) {
			throw new DataParseException("数据不能为空");
		}
		// 获得注册的类
		Class<?> clazz = this.getDataConfig().getRegisterClass();
		
		// 创建对象实例
		Object newInstance = ClassUtil.newInstance(clazz);
		
		// 获得字段的配置
		Map<Integer, DataFieldModel> fieldMap = this.getDataConfig().getFieldMap();
		
		for (int i = 0; i < strs.length; i++) {
			DataFieldModel dataFieldModel = fieldMap.get(i);
			if(dataFieldModel == null) {
				continue;
			}
			String column = strs[i];
			// 类型转换器
			Converter<?> converter = dataFieldModel.getConverter();
			// 格式校验处理器
			ProcessHandler checkedHandler = dataFieldModel.getCheckedHandler();
			// 校验格式
			HandlerArgs args = new HandlerArgs(column);
			boolean handler = checkedHandler.handler(args);
			if(!handler) {
				throw new DataParseException("数据格式校验失败,column=" + column);
			}
			column = (String)args.getObj();
			try {
				// 进行数据类型转化
				Object data = converter.convertValue(column);
				// 通过反射插入数据
				PropertyDescriptor propertyDescriptor = new PropertyDescriptor(dataFieldModel.getField().getName(), clazz);
				propertyDescriptor.getWriteMethod().invoke(newInstance, data);
			} catch (Exception e) {
				throw new DataParseException("字段解析" + column);
			} 
		}
		
		return newInstance;
	}
	/**
	 * @title 将一行数据拆分后的数组解析为对象
	 * @param strs
	 * @return
	 * @throws DataParseException
	 * @author: xue.zhang
	 * @date 2019年1月15日下午2:21:26
	 */
	private List<Object> toList(String[] strs) throws DataParseException {
		// 解析后字段的数量(字段必须是连续的)
		int arrayInterval = this.getDataConfig().getArrayInterval();
		// 获得集合的长度, 等于0的时候，无限解析下去，直到数组的末尾
		int arrayLength = this.getDataConfig().getArrayLength();
		
		List<Object> res = new ArrayList<Object>();
		
		// 获得注册的类
		Class<?> clazz = this.getDataConfig().getRegisterClass();
		
		// 字段以及其配置信息
		Map<Integer, DataFieldModel> fieldMap = this.getDataConfig().getFieldMap();
		
		// 索引的填充
		int fillIndex = 0;
		// 循环的次数
		int index = 1;
		// 数组长度
		int strsLength = strs.length;
		
		www:while (true) {
			if(arrayLength != 0 && arrayLength < index) {//设置集合长度后，已达到最大值
				break;
			}
			
			// 创建对象实例
			Object newInstance = ClassUtil.newInstance(clazz);
			// 解析一个对象
			for (Entry<Integer, DataFieldModel> entry : fieldMap.entrySet()) {
				Integer strsIndex = entry.getKey() + fillIndex;//数组中的索引
				DataFieldModel dataFieldModel = entry.getValue();
				
				if(strsLength - 1 < strsIndex) {//数组获取的长度已经到达最大值，则跳出所有的循环
					break www;
				}
				String column = strs[strsIndex];
				// 类型转换器
				Converter<?> converter = dataFieldModel.getConverter();
				// 格式校验处理器
				ProcessHandler checkedHandler = dataFieldModel.getCheckedHandler();
				// 校验格式
				HandlerArgs args = new HandlerArgs(column);
				boolean handler = checkedHandler.handler(args);
				if(!handler) {
					throw new DataParseException("数据格式校验失败,column=" + column);
				}
				column = (String)args.getObj();
				
				try {
					// 进行数据类型转化
					Object data = converter.convertValue(column);
					// 通过反射插入数据
					PropertyDescriptor propertyDescriptor = new PropertyDescriptor(dataFieldModel.getField().getName(), clazz);
					propertyDescriptor.getWriteMethod().invoke(newInstance, data);
				} catch (Exception e) {
					throw new DataParseException("字段解析" + column);
				}
			}

			// 保存数据
			res.add(newInstance);
			
			fillIndex += arrayInterval;
			index ++;
		}
		
		return res;
	}

}
